package com.smartcruise.data;

import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.amap.api.location.AMapLocation;
import com.smartcruise.data.cruiseData.CruiseContract;
import com.smartcruise.util.FileUtils;
import com.smartcruise.util.Key;
import com.smartcruise.util.ListUtils;
import com.smartcruise.util.network.OssManager;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;

/**
 * Created by FengChaoQun
 * on 2018/1/25 0025
 * 通报数据
 */

public class ReportData extends RealmObject implements Serializable {

    @PrimaryKey
    private String id;
    private String name;//名称
    private String inspectorId;//巡护人员id
    private String auditorId;//审核人员id
    private String patrollingTaskId;//巡航任务的id
    private String contentMap;//通报记录内容的mapJSON字符串
    private String type;//通报类型
    private long createTime;//创建时间
    private String auditResult;//审核结果
    private int auditStatus;//审核状态 0表示未审核 1表示已审核
    private String evaluation;//评语
    private long storageTime;//入库时间
    private String longitude;
    private String latitude;

    /**
     * ***********************************本地字段**********************************
     */
    /**
     * description:服务器端id 在数据上传到服务器后更新该字段
     */
    private String serverId;

    private String originalImages;//本地图片
    private String originalVideos;//本地视频
    private String originalAudios;//本地语音
    private int uploadStatus;//0未上传 1部分上传 2全部上传
    private boolean dataChanged;//标记数据是否改动过 主要是判断被驳回的数据是否需要上传
    private boolean isFromNet;//标记数据是否从服务器下载过来的


    /**
     * ********************************************便捷方法*******************************************
     */

    /**
     * description:上传任务之前对id做一些处理 如果是第一次上传 则不传id
     * 判断任务是否是第一次上传的策略:serverId为空的话表示第一次上传
     * 该方法只有不是数据库中的实体才能调用 因为数据库中不允许修改主键
     */

    public void backUpId() {
        if (isFromNet()) {//如果数据来源于网络 则不用处理
            return;
        }
        setId(serverId);
    }

    /**
     * description:将通报数据的字符串转换为Map
     */
    public Map<String, String> getResultMap() {
        if (TextUtils.isEmpty(contentMap)) {
            return null;
        }
        return JSON.parseObject(contentMap, new TypeReference<Map<String, String>>() {
        });
    }

    /**
     * description:设置通报的文字信息
     */

    public void setText(String text) {
        setSpecialResultData(CruiseContract.NODE_EDIT_DATA_TEXT, Collections.singletonList(text));
    }

    /**
     * description:获取通报的文字
     */

    public String getText() {
        if (getResultMap() != null) {
            String text = getResultMap().get(CruiseContract.NODE_EDIT_DATA_TEXT);
            if (text != null) {
                String[] strings = JSON.parseObject(text, String[].class);
                if (strings != null && strings.length > 0) {
                    return strings[0];
                }
            }
        }
        return null;
    }

    /**
     * description:设置本地源图片路径
     */

    public void setOriginalImage(List<String> images) {
        StringBuilder stringBuilder = new StringBuilder();
        if (ListUtils.isHaveContent(images)) {
            for (String image : images) {
                stringBuilder.append(image).append("#");
            }
        }
        originalImages = stringBuilder.toString();
    }

    /**
     * description:获取本地源文件路径
     */

    public List<String> getOriginalImage() {
        if (TextUtils.isEmpty(originalImages)) {
            return null;
        } else {
            return Arrays.asList(originalImages.split("#"));
        }
    }

    /**
     * description:获取已上传的缩略图
     */

    public List<String> getThumbnailImage() {
        return getSpecialPositionList(CruiseContract.NODE_EDIT_DATA_PICTURE, 2);
    }

    /**
     * description:获取已上传的原图
     */

    public List<String> getNetImage() {
        return getSpecialPositionList(CruiseContract.NODE_EDIT_DATA_PICTURE, 3);
    }

    /**
     * description:设置本地源视频文件路径
     */
    public void setOriginalVideos(List<String> videos) {
        StringBuilder stringBuilder = new StringBuilder();
        if (ListUtils.isHaveContent(videos)) {
            for (String image : videos) {
                stringBuilder.append(image).append("#");
            }
        }
        originalVideos = stringBuilder.toString();
    }

    /**
     * description:获取存储的本地源视频路径
     */
    public List<String> getOriginalVideos() {
        if (TextUtils.isEmpty(originalVideos)) {
            return null;
        } else {
            return Arrays.asList(originalVideos.split(Key.SPLIT));
        }
    }

    /**
     * description:获取已上传的视频缩略图
     */

    public List<String> getThumbnailVideo() {
        return getSpecialPositionList(CruiseContract.NODE_EDIT_DATA_VIDEO, 2);
    }

    /**
     * description:获取已上传的原视频
     */

    public List<String> getNetVideo() {
        return getSpecialPositionList(CruiseContract.NODE_EDIT_DATA_VIDEO, 3);
    }

    /**
     * description:设置本地源语音的文件路径
     */
    public void setOriginalAudios(List<String> audios) {
        StringBuilder stringBuilder = new StringBuilder();
        if (ListUtils.isHaveContent(audios)) {
            for (String image : audios) {
                stringBuilder.append(image).append(Key.SPLIT);
            }
        }
        originalAudios = stringBuilder.toString();
    }

    /**
     * description:获取本地源语音文件路径
     */

    public List<String> getOriginalAudios() {
        if (TextUtils.isEmpty(originalAudios)) {
            return null;
        } else {
            return Arrays.asList(originalAudios.split(Key.SPLIT));
        }
    }

    /**
     * description:获取已上传的语音
     */

    public List<String> getNetAudio() {
        return getSpecialPositionList(CruiseContract.NODE_EDIT_DATA_AUDIO, 2);
    }

    /**
     * description:获取指定类型的文件在指定位置的数据列表
     */

    private List<String> getSpecialPositionList(String type, int position) {
        try {
            if (getResultMap() != null) {
                String text = getResultMap().get(type);
                List<String> stringList = new ArrayList<>();
                if (text != null) {
                    String[] strings = JSON.parseObject(text, String[].class);
                    if (strings != null && strings.length > 0) {
                        for (String string : strings) {
                            String[] details = string.split(Key.SPLIT);
                            if (details.length >= position) {
                                stringList.add(details[position - 1]);
                            }
                        }
                    }
                    return stringList;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * description:判断该通报是否审核通过
     */

    public boolean isAuditSuccess() {
        return CruiseContract.AUDIT_SUCCESS.equals(auditResult);
    }

    /**
     * description:获取可展示的图片
     * 1.如果是本地任务 显示本地图片
     * 2.如果是已上传的任务:
     * (1)如果审核通过 显示网络图片
     * (2)其余的同时显示网络图片和本地图片
     */

    public List<String> getShowImage() {
        if (!isFromNet()) {//本地数据 显示本地图片
            return getOriginalImage();
        } else {
            if (isAuditSuccess()) {
                return getThumbnailImage();
            } else {
                ArrayList<String> arrayList = new ArrayList<>();
                if (ListUtils.isHaveContent(getOriginalImage())) {
                    arrayList.addAll(getOriginalImage());
                }
                if (ListUtils.isHaveContent(getThumbnailImage())) {
                    arrayList.addAll(getThumbnailImage());
                }
                return arrayList;
            }
        }
    }

    /**
     * description:获取可展示的视频
     * 1.如果是本地任务 显示本地视频
     * 2.如果是已上传的任务:
     * (1)如果审核通过 显示网络视频
     * (2)其余的同时显示网络视频和本地视频
     */
    public List<String> getShowVideo() {
        if (!isFromNet()) {//本地数据 显示本地视频
            return getOriginalVideos();
        } else {
            if (isAuditSuccess()) {
                return getNetVideo();
            } else {
                ArrayList<String> arrayList = new ArrayList<>();
                if (ListUtils.isHaveContent(getOriginalVideos())) {
                    arrayList.addAll(getOriginalVideos());
                }
                if (ListUtils.isHaveContent(getNetVideo())) {
                    arrayList.addAll(getNetVideo());
                }
                return arrayList;
            }
        }
    }

    /**
     * description:获取可展示的语音
     * 1.如果是本地任务 显示本地语音
     * 2.如果是已上传的任务:
     * (1)如果审核通过 显示网络语音
     * (2)其余的同时显示网络语音和本地语音
     */

    public List<String> getShowAudio() {
        if (!isFromNet()) {//本地数据 显示本地语音
            return getOriginalAudios();
        } else {
            if (isAuditSuccess()) {
                return getNetAudio();
            } else {
                ArrayList<String> arrayList = new ArrayList<>();
                if (ListUtils.isHaveContent(getOriginalAudios())) {
                    arrayList.addAll(getOriginalAudios());
                }
                if (ListUtils.isHaveContent(getNetAudio())) {
                    arrayList.addAll(getNetAudio());
                }
                return arrayList;
            }
        }
    }

    /**
     * description:获取已经上传的图片 格式没有转化 格式为uuid#缩略图url#原图url
     */

    private List<String> getUploadedImage() {
        if (getResultMap() != null) {
            String text = getResultMap().get(CruiseContract.NODE_EDIT_DATA_PICTURE);
            if (text != null) {
                String[] strings = JSON.parseObject(text, String[].class);
                List<String> list = new ArrayList<>();
                for (String string : strings) {
                    if (!TextUtils.isEmpty(string)) {
                        list.add(string);
                    }
                }
                return list;
            }
        }
        return null;
    }

    /**
     * description:获取已经上传的视频 格式没有转化
     */

    private List<String> getUploadedVideo() {
        if (getResultMap() != null) {
            String text = getResultMap().get(CruiseContract.NODE_EDIT_DATA_VIDEO);
            if (text != null) {
                String[] strings = JSON.parseObject(text, String[].class);
                List<String> list = new ArrayList<>();
                for (String string : strings) {
                    if (!TextUtils.isEmpty(string)) {
                        list.add(string);
                    }
                }
                return list;
            }
        }
        return null;
    }

    /**
     * description:获取已经上传的音频 格式没有转化
     */

    private List<String> getUploadedAudio() {
        if (getResultMap() != null) {
            String text = getResultMap().get(CruiseContract.NODE_EDIT_DATA_AUDIO);
            if (text != null) {
                String[] strings = JSON.parseObject(text, String[].class);
                List<String> list = new ArrayList<>();
                for (String string : strings) {
                    if (!TextUtils.isEmpty(string)) {
                        list.add(string);
                    }
                }
                return list;
            }
        }
        return null;
    }

    /**
     * description:更新已经上传的图片
     */

    public void refreshUploadedImage(List<String> savedImages) {
        if (ListUtils.isHaveContent(savedImages) && ListUtils.isHaveContent(getUploadedImage())) {
            //找出仍然需要保存的数据 剔除不需要保存的数据
            ArrayList<String> needSaveData = new ArrayList<>();
            for (String s : getUploadedImage()) {
                for (String savedImage : savedImages) {
                    if (s.contains(savedImage) && !needSaveData.contains(s)) {
                        needSaveData.add(s);
                    }
                }
            }
            setSpecialResultData(CruiseContract.NODE_EDIT_DATA_PICTURE, needSaveData);
        } else {//没有数据需要保存 保存空数据
            setSpecialResultData(CruiseContract.NODE_EDIT_DATA_PICTURE, Collections.singletonList(""));
        }
    }

    /**
     * description:更新已经上传的视频
     */

    public void refreshUploadedVideo(List<String> savedVideos) {
        if (ListUtils.isHaveContent(savedVideos) && ListUtils.isHaveContent(getUploadedVideo())) {
            //找出仍然需要保存的数据 剔除不需要保存的数据
            ArrayList<String> needSaveData = new ArrayList<>();
            for (String s : getUploadedVideo()) {
                for (String savedVideo : savedVideos) {
                    if (s.contains(savedVideo) && !needSaveData.contains(s)) {
                        needSaveData.add(s);
                    }
                }
            }
            setSpecialResultData(CruiseContract.NODE_EDIT_DATA_VIDEO, needSaveData);
        } else {//没有数据需要保存 保存空数据
            setSpecialResultData(CruiseContract.NODE_EDIT_DATA_VIDEO, Collections.singletonList(""));
        }
    }

    /**
     * description:更新已经上传的音频
     */

    public void refreshUploadedAudio(List<String> savedAudios) {
        if (ListUtils.isHaveContent(savedAudios) && ListUtils.isHaveContent(getUploadedAudio())) {
            //找出仍然需要保存的数据 剔除不需要保存的数据
            ArrayList<String> needSaveData = new ArrayList<>();
            for (String s : getUploadedAudio()) {
                for (String savedAudio : savedAudios) {
                    if (s.contains(savedAudio) && !needSaveData.contains(s)) {
                        needSaveData.add(s);
                    }
                }
            }
            setSpecialResultData(CruiseContract.NODE_EDIT_DATA_AUDIO, needSaveData);
        } else {//没有数据需要保存 保存空数据
            setSpecialResultData(CruiseContract.NODE_EDIT_DATA_AUDIO, Collections.singletonList(""));
        }
    }

    /**
     * description:将文字信息添加到节点任务结果中
     * 如果没有文字信息 也要按格式保存空字符串
     */

    public void buildText() {
        if (TextUtils.isEmpty(getText())) {
            setText("");
        }
    }

    /**
     * description:将图片信息添加到任务结果中 从服务器下载的任务需要考虑保留已经上传的图片
     * 1.如果是本地任务 则直接将已上传的图片清空 重新构造
     * 2.如果是从服务器下载的任务 则：
     * (1).保留已经上传的图片
     * (2).添加本地图片
     *
     * @param all 标记是否需要添加原图路径
     */

    public void buildImages(boolean all) {//图片格式为 uuid#压缩图片路径#原图路径
        List<String> stringList = getUploadedImage();
        if (stringList == null) {
            stringList = new ArrayList<>();
        }
        if (isFromNet()) {//来自服务器的数据 需要保留以前已经上传的图片路径
            if (ListUtils.isHaveContent(getOriginalImage())) {//有数据的话保存
                //剔除掉那些已经存的内容 避免重复添加 因为本地图片可能不止一次上传过
                ArrayList<String> removedData = new ArrayList<>();
                for (String s : getOriginalImage()) {
                    for (String s1 : stringList) {
                        if (s1.contains(FileUtils.getFileSimpleName(s))) {
                            removedData.add(s1);
                        }
                    }
                }
                //从已上传的数据中剔除本地存在的文件 接下来会更新这部分内容  ↓↓↓
                stringList.removeAll(removedData);

                for (String s : getOriginalImage()) {
                    String s1 = FileUtils.getFileSimpleName(s) + "#" + OssManager.getOssUrl(FileUtils.getFileThumName(s)) + "#";
                    if (all) {
                        s1 = s1 + OssManager.getOssUrl(FileUtils.getFileSimpleName(s)) + "#";
                    }
                    stringList.add(s1);
                }
            }
        } else {//本地数据
            stringList.clear();//本地数据不用考虑已经上传的图片 直接清空 重新构造
            if (ListUtils.isHaveContent(getOriginalImage())) {
                for (String s : getOriginalImage()) {
                    String s1 = FileUtils.getFileSimpleName(s) + "#" + OssManager.getOssUrl(FileUtils.getFileThumName(s)) + "#";
                    if (all) {
                        s1 = s1 + OssManager.getOssUrl(FileUtils.getFileSimpleName(s)) + "#";
                    }
                    stringList.add(s1);
                }
            }
        }

        setSpecialResultData(CruiseContract.NODE_EDIT_DATA_PICTURE, stringList);
    }

    /**
     * description:将视频信息添加到任务结果中
     * 1.如果是本地任务 则直接将已上传的视频清空 重新构造
     * 2.如果是从服务器下载的任务 则：
     * (1).保留已经上传的视频
     * (2).添加本地视频
     *
     * @param all 标记是否需要添加原视频路径
     */

    public void buildVideos(boolean all) {//视频格式为 uuid#缩略图路径#源文件路径
        List<String> stringList = getUploadedVideo();
        if (stringList == null) {
            stringList = new ArrayList<>();
        }
        if (isFromNet()) {
            if (ListUtils.isHaveContent(getOriginalVideos())) {//有数据的话保存
                //剔除掉那些已经存的内容 避免重复添加
                ArrayList<String> removedData = new ArrayList<>();
                for (String s : getOriginalVideos()) {
                    for (String s1 : stringList) {
                        if (s1.contains(FileUtils.getFileSimpleName(s))) {
                            removedData.add(s1);
                        }
                    }
                }
                stringList.removeAll(removedData);

                for (String s : getOriginalVideos()) {
                    String s1 = FileUtils.getFileSimpleName(s) + "#" + OssManager.getOssUrl(FileUtils.getVideoThumName(s)) + "#";
                    if (all) {
                        s1 = s1 + OssManager.getOssUrl(FileUtils.getFileSimpleName(s)) + "#";
                    }
                    stringList.add(s1);
                }
            }
        } else {
            stringList.clear();
            if (ListUtils.isHaveContent(getOriginalVideos())) {
                for (String s : getOriginalVideos()) {
                    String s1 = FileUtils.getFileSimpleName(s) + "#" + OssManager.getOssUrl(FileUtils.getVideoThumName(s)) + "#";
                    if (all) {
                        s1 = s1 + OssManager.getOssUrl(FileUtils.getFileSimpleName(s)) + "#";
                    }
                    stringList.add(s1);
                }
            }
        }

        setSpecialResultData(CruiseContract.NODE_EDIT_DATA_VIDEO, stringList);
    }

    /**
     * description:将语音信息添加到任务结果中
     * 1.如果是本地任务 则直接将已上传的语音清空 重新构造
     * 2.如果是从服务器下载的任务 则：
     * (1).保留已经上传的语音
     * (2).添加本地语音
     */

    public void buildAudio() {//录音格式为 uuid#源文件路径
        List<String> stringList = getUploadedAudio();
        if (stringList == null) {
            stringList = new ArrayList<>();
        }
        if (isFromNet()) {
            if (ListUtils.isHaveContent(getOriginalAudios())) {//有数据的话保存
                //剔除掉那些已经存的内容 避免重复添加
                ArrayList<String> removedImage = new ArrayList<>();
                for (String s : getOriginalAudios()) {
                    for (String s1 : stringList) {
                        if (s1.contains(FileUtils.getFileSimpleName(s))) {
                            removedImage.add(s1);
                        }
                    }
                }
                stringList.removeAll(removedImage);

                for (String s : getOriginalAudios()) {
                    String s1 = FileUtils.getFileSimpleName(s) + "#" + OssManager.getOssUrl(FileUtils.getFileSimpleName(s)) + "#";
                    stringList.add(s1);
                }

            }
        } else {
            stringList.clear();
            if (ListUtils.isHaveContent(getOriginalAudios())) {
                for (String s : getOriginalAudios()) {
                    String s1 = FileUtils.getFileSimpleName(s) + "#" + OssManager.getOssUrl(FileUtils.getFileSimpleName(s)) + "#";
                    stringList.add(s1);
                }
            }
        }

        setSpecialResultData(CruiseContract.NODE_EDIT_DATA_AUDIO, stringList);
    }

    /**
     * description:将指定类型的数据填充到结果里面
     *
     * @param type 数据类型 {@link CruiseContract#NODE_EDIT_DATA_VIDEO}等
     * @param data 数据列表
     */

    private void setSpecialResultData(String type, List<String> data) {
        Map<String, String> map = getResultMap();
        if (map == null) {
            map = new HashMap<>();
        }
        map.put(type, JSON.toJSON(data).toString());
        setContentMap(JSON.toJSON(map).toString());
    }

    /**
     * description:构造概要结果信息
     */

    public void buildTaskSimpleData() {
        buildText();
        buildImages(false);
        buildAudio();
        buildVideos(false);
    }

    /**
     * description:构造节点全部结果信息
     */

    public void buildTaskAllData() {
        buildText();
        buildImages(true);
        buildAudio();
        buildVideos(true);
    }

    /**
     * description:清空数据
     */

    public void cleanData() {
        setContentMap(null);
        setOriginalImage(null);
        setOriginalVideos(null);
        setOriginalAudios(null);
    }

    /**
     * description:清空本地资源
     */

    public void clearOriginalFiles() {
        setOriginalImage(null);
        setOriginalVideos(null);
        setOriginalAudios(null);
    }

    /**
     * description:检查是否含有大的本地数据
     */

    public boolean isHaveBigLocalFile() {
        return ListUtils.isHaveContent(getOriginalImage()) || ListUtils.isHaveContent(getOriginalVideos());
    }

    /**
     * description:检查内容是否齐全
     */

    public boolean checkLocalContent() {
        if (TextUtils.isEmpty(getType())) {
            return false;
        }
        if (TextUtils.isEmpty(getAuditorId())) {
            return false;
        }
        return !TextUtils.isEmpty(getText()) || ListUtils.isHaveContent(getOriginalImage())
                || ListUtils.isHaveContent(getOriginalAudios()) || ListUtils.isHaveContent(getOriginalVideos());
    }

    /**
     * description:保存坐标
     */

    public void setLocation(AMapLocation aMapLocation) {
        if (aMapLocation != null) {
            setLatitude(String.valueOf(aMapLocation.getLatitude()));
            setLongitude(String.valueOf(aMapLocation.getLongitude()));
        }
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getInspectorId() {
        return inspectorId;
    }

    public void setInspectorId(String inspectorId) {
        this.inspectorId = inspectorId;
    }

    public String getAuditorId() {
        return auditorId;
    }

    public void setAuditorId(String auditorId) {
        this.auditorId = auditorId;
    }

    public String getPatrollingTaskId() {
        return patrollingTaskId;
    }

    public void setPatrollingTaskId(String patrollingTaskId) {
        this.patrollingTaskId = patrollingTaskId;
    }

    public String getContentMap() {
        return contentMap;
    }

    public void setContentMap(String contentMap) {
        this.contentMap = contentMap;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public long getCreateTime() {
        return createTime;
    }

    public void setCreateTime(long createTime) {
        this.createTime = createTime;
    }

    public String getServerId() {
        return serverId;
    }

    public void setServerId(String serverId) {
        this.serverId = serverId;
    }

    public int getUploadStatus() {
        return uploadStatus;
    }

    public void setUploadStatus(int uploadStatus) {
        this.uploadStatus = uploadStatus;
    }

    public String getAuditResult() {
        return auditResult;
    }

    public void setAuditResult(String auditResult) {
        this.auditResult = auditResult;
    }

    public int getAuditStatus() {
        return auditStatus;
    }

    public void setAuditStatus(int auditStatus) {
        this.auditStatus = auditStatus;
    }

    public boolean isDataChanged() {
        return dataChanged;
    }

    public void setDataChanged(boolean dataChanged) {
        this.dataChanged = dataChanged;
    }

    public void setFromNet(boolean fromNet) {
        isFromNet = fromNet;
    }

    public boolean isFromNet() {
        return this.isFromNet;
    }

    public String getEvaluation() {
        return evaluation;
    }

    public void setEvaluation(String evaluation) {
        this.evaluation = evaluation;
    }

    public long getStorageTime() {
        return storageTime;
    }

    public void setStorageTime(long storageTime) {
        this.storageTime = storageTime;
    }

    public String getLongitude() {
        return longitude;
    }

    public void setLongitude(String longitude) {
        this.longitude = longitude;
    }

    public String getLatitude() {
        return latitude;
    }

    public void setLatitude(String latitude) {
        this.latitude = latitude;
    }

}
